home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / bpatch / bpatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-19  |  35.1 KB  |  1,751 lines

  1. /*T bpatch - A binary file patch/dump utility */
  2. /*S Introduction */
  3. /*F bpatch ***********************************************************
  4. * bpatch
  5. * by Garry M Johnson - 09/17/84
  6. * (C) Copyright 1984, 1985
  7. *
  8. * Change History:
  9. *  03/05/86 - added further terminal independence
  10. *             added use of ioctl (see main and mstdin)
  11. *             added -D versus -d command line option
  12. *             added use of standard getopt
  13. *             cleaned up code, eliminated function "ikf"
  14. *             added original versions of ezlib functions, such as
  15. *               icc, setterm, cm, mstdin, erase, length, move
  16. *             added ^R, ^Q, ^N, and ^P commands
  17. *             added ^F, !, and ^X (-X) commands
  18. *              changed name to "bpatch"
  19. *              added direct address command (g)
  20. *             added ASCII search capability
  21. *  07/07/86 - converted to use curses
  22. *             modified direct addressing to use suffixes
  23. *             updated HELP function
  24. *
  25. *   Steven List @ Benetics Corporation, Mt. View, CA
  26. *   {cdp,engfocus,idi,oliveb,plx,tolerant}!bene!luke!itkin
  27. *********************************************************************/
  28. /*E*/
  29. /*S includes, globals, and defines */
  30. /*Page Eject*/
  31. #include    <curses.h>
  32. #include <fcntl.h>
  33. #include <signal.h>
  34. #include <ctype.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37.  
  38. static int pbrk = 0;
  39. struct stat sb;
  40.  
  41. void icc ();
  42. void copyrec ();
  43. void schwapp ();
  44.  
  45.     /* ------------------------------------------------------------ */
  46.     /* Some defines added by the moderator to get it work on 4.2    */
  47.     /* ------------------------------------------------------------ */
  48. #ifdef    MOD_HAX
  49.     /* Fifos?  We ain't got no steenkin' fifos. */
  50. #define S_IFIFO        123450
  51.     /* "Spelling differences." */
  52. #define beep()        fprintf (stderr, "\007")
  53. #define cbreak()    crmode()
  54.     /* Our curses doesn't translate keypad keys to single characters. */
  55. #define keypad(a, b)    /* null */
  56. #define KEY_UP        '^'
  57. #define KEY_DOWN    'v'
  58. #define KEY_LEFT    '<'
  59. #define KEY_RIGHT    '>'
  60. #define KEY_HOME    '@'
  61. #endif    /* MOD_HAX */
  62.  
  63.  
  64.     /* ------------------------------------------------------------ */
  65.     /* Some convenient defines                                      */
  66.     /* ------------------------------------------------------------ */
  67.  
  68. #define DEL '\177'
  69. #define HEX 1
  70. #define ALPHA 0
  71.  
  72.     /* ------------------------------------------------------------ */
  73.     /* general purpose identification and control variables         */
  74.     /* ------------------------------------------------------------ */
  75.  
  76. char    filename[64];            /* current file being examined        */
  77. char    record[16][16];            /* record (page) buffer                */
  78. char    unch_rec[16][16];        /* record before any changes        */
  79. int     zp;                        /* current input character            */
  80.  
  81. int        block = 0;                /* block size if -b in command        */
  82. int        block_spec;                /* true if file is block special    */
  83. int        bytes = 0;                /* number of bytes from last read    */
  84. int        char_spec;                /* true if file is char special        */
  85. int        debug = 0;                /* true if debug is turned on        */
  86. int        dir_spec;                /* true if file is directory        */
  87. int        dump = 0;                /* nonzero if dump instead of change*/
  88. int        ebcdic = 0;                /* true if -e option                */
  89. int        fifo_spec;                /* true if file is fifo                */
  90. int        honly = 0;                /* true if dump is to be hex only    */
  91. int        mod = 0;                /* true if record has been modified    */
  92. int        pause = 0;                /* true if -p option                */
  93. int        rawfile = 0;            /* true if file is c/b/p            */
  94. int        reclen = 0;                /* record length, if -r                */
  95. int        recno = 0;                /* current record (page) number        */
  96. int        stay = 0;                /* true if no position change         */
  97. int        swab = 0;                /* true if byte swapping is on        */
  98. int        windowed = 0;            /* true if windowing - not dump        */
  99.  
  100. long    position = 0;            /* byte address in file                */
  101.  
  102. WINDOW *hexwin = NULL;
  103. WINDOW *alphawin = NULL;
  104. WINDOW *errwin = NULL;
  105.  
  106. /*S main - control all the work from here */
  107. /*H main *************************************************************
  108. *
  109. *                            main
  110. *
  111. *    set up the globals, initilize the state, and process the file
  112. *
  113. *********************************************************************/
  114. /*E*/
  115. main (argc, argv)
  116. int argc;
  117. char *argv[];
  118. {
  119.     extern WINDOW *subwin ();
  120.     extern WINDOW *newwin ();
  121.  
  122. #ifdef    MOD_HAX
  123. #else    /* use original code... */
  124.     struct termio asis;
  125. #endif    /* MOD_HAX */
  126.  
  127.     register char    *cp;                /* general purpose char ptr    */
  128.     extern   char    *gets ();            /* get string from stdin    */
  129.              char    m = '\017';            /* mask for hex edit        */
  130.              char    response[512];        /* general purpose buffer    */
  131.              int     z;                    /* character read in        */
  132.          
  133.     void    breakp ();            /* signal trapping function            */
  134.     int        c;                    /* current screen column            */
  135.     int        change = 0;            /* true if cmd line option toggled    */
  136.     int        fid;                /* file descriptor                    */
  137.     int        firstfile;            /* arg # of first file in cmd line    */
  138.     int        h;                    /* temp for hex edit                */
  139.     int        i;                    /* general purpose loop index        */
  140.     int        j;                    /* general purpose loop index        */
  141.     int        r;                    /* current screen row                */
  142.     int        hexc;                /* current cursor column in hexwin    */
  143.  
  144.     long    byteaddr;            /* planned byte address for 'G'        */
  145.     long    size;                /* file size in bytes                */
  146.     long    status;                /* EOF if at end of file or error    */
  147.  
  148.     extern int optind;            /* getopt index into argv            */
  149.     extern char *optarg;        /* getopt pointer to opt arg        */
  150.  
  151.     extern long getnum ();
  152.     extern char *getstring ();    /* get a string from the cmd line    */
  153.     extern void reset ();        /* exit function - reset terminal    */
  154.  
  155.     /* ------------------------------------------------------------ */
  156.     /* set up signal handling                                       */
  157.     /* ------------------------------------------------------------ */
  158.  
  159.     if (!dump) signal (SIGINT, breakp);
  160.  
  161.     signal (SIGTERM, reset);
  162.  
  163.     /* ------------------------------------------------------------ */
  164.     /* process command line arguments                               */
  165.     /* ------------------------------------------------------------ */
  166.  
  167.     while ((i = getopt (argc, argv, "r:dD:b:pxXse")) != EOF)
  168.     {
  169.         switch (i)
  170.         {
  171.             case    'b':        /* blocking                    */
  172.                 block = atoi (optarg);
  173.                 if (block < 1 || block > 10240)
  174.                 {
  175.                     fprintf (stderr,
  176.                         "invalid block size: %d\n", block);
  177.                     exit (1);
  178.                 }
  179.                 break;
  180.             case    'd':        /* straight dump - no limit    */
  181.                 dump = -1;
  182.                 break;
  183.             case    'D':        /* dump - page count spec    */
  184.                 dump = atoi (optarg);
  185.                 break;
  186.             case    'e':        /* file is ebcdic            */
  187.                 ebcdic = 1;
  188.                 break;
  189.             case    'p':        /* pause between pages - dump    */
  190.                 pause = 1;
  191.                 break;
  192.             case    'r':        /* record length for dump        */
  193.                 reclen = atoi (optarg);
  194.                 break;
  195.             case    's':        /* byte swapping required        */
  196.                 swab = 1;
  197.                 break;
  198.             case    'x':        /* hex dump only                */
  199.                 honly = 1;
  200.                 break;
  201.             case    'X':
  202.                 debug = 1;
  203.                 break;
  204.             default:            /* uhoh                            */
  205.                 fprintf (stderr,
  206. "usage: bpatch [ -b blocksz ] [ -d<ump> ] [ -D pagecnt ] [ -e<bcdic> ]\n");
  207.                 fprintf (stderr,
  208. "              [ -p<ause> ] [ -r reclen ] [ -s<wap bytes> ] [ -x<only> ]\n");
  209.                 exit (1);
  210.         }
  211.     }
  212.  
  213.     /* ------------------------------------------------------------ */
  214.     /* check for valid combinations of options                      */
  215.     /* ------------------------------------------------------------ */
  216.  
  217.     if ((honly || block || reclen || pause ) && !dump)
  218.     {
  219.         fprintf (stderr, "-x|-b|-r|-p requires -d or -D\n");
  220.         exit (2);
  221.     }
  222.  
  223.     /* ------------------------------------------------------------ */
  224.     /* At least one file name must be specified on the cmd line     */
  225.     /* ------------------------------------------------------------ */
  226.  
  227.     if (optind == argc)
  228.     {
  229.         fprintf (stderr, "no file name(s) specified\n");
  230.         exit (2);
  231.     }
  232.  
  233.     /* ------------------------------------------------------------ */
  234.     /* set up the screen, if this is an interactive session         */
  235.     /* ------------------------------------------------------------ */
  236.  
  237.     if (!dump)
  238.     {
  239.         windowed = 1;
  240.         initscr ();
  241.         nonl ();
  242.         noecho ();
  243.         cbreak ();
  244.         keypad (stdscr, TRUE);
  245.         hexwin = subwin (stdscr, 16, 48, 4, 4);
  246.         keypad (hexwin, TRUE);
  247.         alphawin = subwin (stdscr, 16, 16, 4, 57);
  248.         keypad (alphawin, TRUE);
  249.         errwin = subwin (stdscr, 1, 80, 23, 0);
  250.  
  251. #ifdef    MOD_HAX
  252.         /* This is not exactly what the original code does,
  253.            but it's good enough.  -r$ */
  254.         raw();
  255. #else    /* use original code... */
  256.         ioctl (0, TCGETA, &asis);
  257.         asis.c_cc[VINTR] = '\0';
  258.         asis.c_iflag &= ~IXON;
  259.         asis.c_iflag &= ~IXOFF;
  260.         asis.c_iflag &= ~IXANY;
  261.         ioctl (0, TCSETA, &asis);
  262. #endif    /* MOD_HAX */
  263.     }
  264.  
  265.     /* ------------------------------------------------------------ */
  266.     /* save the first file's index for backing up later             */
  267.     /* ------------------------------------------------------------ */
  268.  
  269.     firstfile = optind;
  270.  
  271.     /* ------------------------------------------------------------ */
  272.     /* open the first file                                          */
  273.     /* ------------------------------------------------------------ */
  274.  
  275.     for (fid = -1; fid < 0 && optind < argc;)
  276.     {
  277.         fid = ckfile (argv[optind], &size);
  278.         if (fid < 0) optind++;
  279.     }
  280.     if (fid < 0)
  281.     {
  282.         reset (0);
  283.         fprintf (stderr, "could not handle the file list\n");
  284.         exit (2);
  285.     }
  286.  
  287.     strncpy (filename, argv[optind], sizeof filename);
  288.  
  289.     if (block != 0)
  290.     {
  291.         size = -1;
  292.     }
  293.  
  294.     recno = 0;
  295.     stay = 0;
  296.     mod = 0;
  297.     status = 0;
  298.  
  299.     /* ------------------------------------------------------------ */
  300.     /* Until the user exits...                                      */
  301.     /* ------------------------------------------------------------ */
  302.  
  303.     if (!dump) clear ();
  304.  
  305.     while (status != EOF)
  306.     {
  307.     /* ------------------------------------------------------------ */
  308.     /* change of location - read and display                        */
  309.     /* ------------------------------------------------------------ */
  310.         if (stay == 0)
  311.         {
  312.             position = lseek (fid, (long)(recno * 256), 0);
  313.  
  314.             if ((bytes = bread (fid, record, 256, block)) < 0)
  315.             {
  316.                 errmsg ("error on reading file %s", filename);
  317.                 status = EOF;
  318.                 continue;
  319.             }
  320.             if (bytes > 0)
  321.             {
  322.                 if (swab) schwapp (record, 256);
  323.  
  324.                 copyrec (record, unch_rec, sizeof record);
  325.  
  326.                 show (bytes, record, filename, size, recno,
  327.                         position, m,reclen, dump, ebcdic, swab,
  328.                         block, honly);
  329.             }
  330.             mod = 0;
  331.         }
  332.     /* ------------------------------------------------------------ */
  333.     /* not interactive - keep dumping or open next file             */
  334.     /* ------------------------------------------------------------ */
  335.         if (dump)
  336.         {
  337.             if ((dump < 0 && bytes == 0) || (--dump == 0))
  338.             {
  339.                 if (optind == argc) status = EOF;
  340.                 else
  341.                 {
  342.                     close (fid);
  343.                     fid = -1;
  344.                     for (optind++; fid < 0 && optind < argc;)
  345.                     {
  346.                         fid = ckfile (argv[optind], &size);
  347.                         if (fid < 0) optind++;
  348.                     }
  349.  
  350.                     strncpy (filename, argv[optind], sizeof filename);
  351.  
  352.                     if (block != 0)
  353.                     {
  354.                         size = -1;
  355.                     }
  356.                     recno = 0;
  357.                     stay = 0;
  358.                     status = lseek (fid, (long)0, 0);
  359.                 }
  360.             }
  361.             ++recno;
  362.     /* ------------------------------------------------------------ */
  363.     /* if pause, beep and wait                                      */
  364.     /* ------------------------------------------------------------ */
  365.             if (status != EOF && pause)
  366.             {
  367.                 pbrk = 0;
  368.                 fprintf (stderr, "\007");
  369.                 gets (response);
  370.  
  371.                 if (pbrk) status = EOF;
  372.             }
  373.  
  374.             continue;
  375.         }
  376.     /* ------------------------------------------------------------ */
  377.     /* if we got here, this is an interactive session               */
  378.     /* ------------------------------------------------------------ */
  379.         stay = 0;
  380.         move (22, 0);
  381.     /* ------------------------------------------------------------ */
  382.     /* get the user's command                                       */
  383.     /* ------------------------------------------------------------ */
  384.         response[0] = EOF;
  385.         mvaddstr (22, 0, "> ");
  386.         clrtoeol ();
  387.         refresh ();
  388.         zp = getch ();
  389.  
  390.         if (debug && !dump)
  391.         {
  392.             if (isascii (zp) && isprint (zp))
  393.                 errmsg ("command entered is %c", zp);
  394.             else errmsg ("command entered is ^%c (%#x)", zp + '@', zp);
  395.             getch ();
  396.         }
  397.  
  398.         if (isascii (zp) && isalpha (zp) && islower (zp))
  399.             zp = toupper (zp);
  400.     /* ------------------------------------------------------------ */
  401.     /* here we go - what does the user want?                        */
  402.     /* ------------------------------------------------------------ */
  403.         refresh ();
  404.  
  405.         switch (zp)
  406.         { 
  407.             case    '!':            /* shell escape                */
  408.                 echo ();
  409.                 move (23,0);
  410.                 clrtoeol ();
  411.                 addstr ("shell command: ");
  412.                 refresh ();
  413.                 getstr (response);
  414.                 erase ();
  415.                 refresh ();
  416.                 nl ();
  417.                 system (response);
  418.                 noecho ();
  419.                 nonl ();
  420.                 move (23,0);
  421.                 standout ();
  422.                 addstr (" <Press any key> ");
  423.                 standend ();
  424.                 clrtoeol ();
  425.                 refresh ();
  426.                 getch ();
  427.                 clear ();
  428.                 break;
  429.  
  430.             case    '?':            /* HELP                        */
  431.                 dbg_msg ("Help");
  432.                 dohelp ();
  433.                 touchwin (stdscr);
  434.                 refresh ();
  435.                 stay = 1;
  436.                 break;
  437.  
  438.             case    '/':            /* search for a string        */
  439.                 stay = 1;
  440.                 if (mod)
  441.                 {
  442.                     errmsg ("No write since last change");
  443.                 }
  444.                 else search (fid, zp);
  445.                 break;
  446.  
  447.             case '-':                /* toggle options            */
  448.                 zp = getch ();
  449.                 stay = 1;
  450.                 change = 0;
  451.                 switch (zp)
  452.                 {
  453.                     case 'a': /* ascii */
  454.                         if (ebcdic)
  455.                         {
  456.                             dbg_msg ("toggle to ascii");
  457.                             change = 1;
  458.                         }
  459.                         ebcdic = 0;
  460.                         break;
  461.  
  462.                     case 'e': /* ebcdic */
  463.                         if (ebcdic == 0)
  464.                         {
  465.                             dbg_msg ("toggle to ebcdic");
  466.                             change = 1;
  467.                         }
  468.                         ebcdic = 1;
  469.                         break;
  470.  
  471.                     case 's': /* swab */
  472.                         dbg_msg ("toggle byte swap");
  473.                         change = 1;
  474.                         schwapp (record, 256);
  475.                         swab = !swab;
  476.                         break;
  477.                 }
  478.                 if (change)
  479.                 {
  480.                     show (bytes, record, filename, size,
  481.                             recno, position, m,reclen, dump,
  482.                             ebcdic, swab, block, honly);
  483.                 }
  484.  
  485.                 break;
  486.  
  487.             case '\022':            /* redraw screen (^R)        */
  488.                 clear ();
  489.                 show (bytes, record, filename, size, recno,
  490.                       position, m, reclen, dump, ebcdic,
  491.                       swab, block, honly);
  492.                 stay = 1;
  493.                 break;
  494.             
  495.             case    '\030':            /* toggle debug (^X)        */
  496.                 debug = !debug;
  497.                 break;
  498.  
  499.             case    '\006':            /* new file (^F)            */
  500.                 close (fid);
  501.                 fid = ckfile (cp = getstring (), &size);
  502.                 if (fid < 0)
  503.                 {
  504.                     fid = ckfile (filename, &size);
  505.                 }
  506.                 else
  507.                 {
  508.                     strncpy (filename, cp, sizeof filename);
  509.                     stay = 0;
  510.                     recno = 0;
  511.                 }
  512.                 break;
  513.  
  514.             case    '\016':            /* next file (^N)            */
  515.                 if (mod)
  516.                 {
  517.                     errmsg ("No write since last change");
  518.                     stay = 1;
  519.                 }
  520.                 else if (optind == (argc - 1))
  521.                 {
  522.                     errmsg ("No more files");
  523.                     stay = 1;
  524.                 }
  525.                 else
  526.                 {
  527.                     close (fid);
  528.                     for (fid = -1, optind++; fid < 0 && optind < argc;)
  529.                     {
  530.                         fid = ckfile (argv[optind], &size);
  531.                         if (fid < 0) optind++;
  532.                     }
  533.                     if (fid < 0)
  534.                     {
  535.                         errmsg ("could not handle the file list");
  536.                         reset (0);
  537.                     }
  538.                     strncpy (filename, argv[optind], sizeof filename);
  539.                     stay = 0;
  540.                     recno = 0;
  541.                 }
  542.                 break;
  543.  
  544.             case    '\020':            /* prev file (^P)            */
  545.                 if (mod)
  546.                 {
  547.                     errmsg ("No write since last change");
  548.                     stay = 1;
  549.                 }
  550.                 else if (optind == firstfile)
  551.                 {
  552.                     errmsg ("No previous file");
  553.                     stay = 1;
  554.                 }
  555.                 else
  556.                 {
  557.                     close (fid);
  558.                     for (fid = -1, optind--; fid < 0 && optind >= firstfile;)
  559.                     {
  560.                         fid = ckfile (argv[optind], &size);
  561.                         if (fid < 0) optind--;
  562.                     }
  563.                     if (fid < 0)
  564.                     {
  565.                         errmsg ("could not handle the file list");
  566.                         reset (0);
  567.                     }
  568.                     strncpy (filename, argv[optind], sizeof filename);
  569.                     stay = 0;
  570.                     recno = 0;
  571.                 }
  572.                 break;
  573.  
  574.             case    '\021':        /* quit absolutely (^Q)        */
  575.                 status = EOF;
  576.                 break;
  577.  
  578.             case DEL:            /* quit with check            */
  579.             case 'Q': /* quit */
  580.                 if (mod)
  581.                 {
  582.                     errmsg ("No write since last change!");
  583.                     stay = 1;
  584.                 }
  585.                 else
  586.                 {
  587.                     status = EOF;
  588.                 }
  589.                 break;
  590.  
  591.             case '\\': /* back up 1 record */
  592.                 if (mod)
  593.                 {
  594.                     errmsg ("No write since last change");
  595.                     stay = 1;
  596.                 }
  597.                 else
  598.                 {
  599.                     if (recno > 0)
  600.                     {
  601.                         --recno;
  602.                         stay = 0;
  603.  
  604.                         status = lseek (fid, (long)recno*256, 0);
  605.                         if (status < 0)
  606.                         {
  607.                             move (22, 0);
  608.                             clrtoeol ();
  609.                             perror (filename);
  610.                             errmsg ("error positioning in file");
  611.                             beep ();
  612.                             ++recno;
  613.                             stay = 1;
  614.                         }
  615.                     }
  616.                     else
  617.                     {
  618.                         errmsg ("No previous records");
  619.                         beep ();
  620.                         stay = 1;
  621.                     }
  622.                 }
  623.                 break; 
  624.  
  625.             case 'F': /* go to first record */
  626.                 if (mod)
  627.                 {
  628.                     errmsg ("No write since last change");
  629.                     stay = 1;
  630.                 }
  631.                 else
  632.                 {
  633.                     status = lseek (fid, (long)0, 0);
  634.                     recno = 0;
  635.                 }
  636.                 break;
  637.  
  638.             case 'L': /* go to last record */
  639.                 if (mod)
  640.                 {
  641.                     errmsg ("No write since last change");
  642.                     stay = 1;
  643.                 }
  644.                 else
  645.                 {
  646.                     position = lseek (fid, (long)0, 2);
  647.                     recno = position / 256;
  648.                     j = position % 256;
  649.                     if (j == 0) --recno;
  650.                     status = lseek (fid, (long)(recno*256), 0);
  651.                 }
  652.                 break;
  653.  
  654.             case 'U':            /* undo changes                    */
  655.                 stay = 1;
  656.                 mod = 0;
  657.                 copyrec (unch_rec, record, sizeof record);
  658.                 show (bytes, record, filename, size, recno,
  659.                         position, m,reclen, dump, ebcdic, swab,
  660.                         block, honly);
  661.                 break;
  662.  
  663.             case 'R': /* re-read record */
  664.                 status = lseek (fid, (long)recno*256, 0);
  665.                 break;
  666.  
  667.             case '0': /* go to some address */
  668.             case '1':
  669.             case '2':
  670.             case '3':
  671.             case '4':
  672.             case '5':
  673.             case '6':
  674.             case '7':
  675.             case '8':
  676.             case '9':
  677.                 if (mod)
  678.                 {
  679.                     errmsg ("No write since last change");
  680.                     stay = 1;
  681.                 }
  682.                 else
  683.                 {
  684.                     byteaddr = getnum (zp, FALSE);
  685.                     stay = 1;
  686.                     errmsg ("Position to byte %ld", byteaddr);
  687.                     if (!rawfile && byteaddr > size)
  688.                     {
  689.                         errmsg ("Address outside file");
  690.                         beep ();
  691.                     }
  692.                     else if (byteaddr / 256 != recno)
  693.                     {
  694.                         recno = byteaddr / 256;
  695.                         status = lseek (fid, (long)recno * 256, 0);
  696.                         stay = 0;
  697.                     }
  698.                 }
  699.                 break;
  700.  
  701.             case 'A': /* alpha modify */
  702.                 stay = 1;
  703.                 r = c = 0;
  704.                 dbg_msg ("edit ascii");
  705.                 if (bytes == 0) break;
  706.                 touchwin (stdscr);
  707.                 refresh ();
  708.                 wmove (alphawin, r, c);
  709.                 wrefresh (alphawin);
  710.  
  711.                 while ((z = wgetch (alphawin)) != DEL)
  712.                 {
  713.                     if (!arrow (z, &r, &c))
  714.                     {
  715.                         if (isascii (z))
  716.                         {
  717.                             if (isprint (z)) waddch (alphawin, z);
  718.                             else             waddch (alphawin, '.');
  719.  
  720.                             if (ebcdic) icc (&z, 1,"AE");
  721.  
  722.                             record[r][c] = z;
  723.                             mod = 1;
  724.  
  725.                             hexc = c * 3;
  726.                             wmove (hexwin, r, hexc);
  727.                             if (record[r][c] < '\0')
  728.                             {
  729.                                 wprintw (hexwin, "%x%x",
  730.                                     (record[r][c] >> 4) & m,
  731.                                     record[r][c] & m);
  732.                             }
  733.                             else
  734.                             {
  735.                                 wprintw (hexwin, "%02x", record[r][c]);
  736.                             }
  737.                             wrefresh (hexwin);
  738.  
  739.                         }
  740.                         else
  741.                         {
  742.                             beep ();
  743.                         }
  744.  
  745.                         if (c == 15)
  746.                         {
  747.                             if (r == 15) beep ();
  748.                             else
  749.                             {
  750.                                 c = 0;
  751.                                 ++r;
  752.                             }
  753.                         }
  754.                         else
  755.                         {
  756.                             c++;
  757.                         }
  758.                     }
  759.                     if (r * 16 + c >= bytes)
  760.                     {
  761.                         beep ();
  762.                         r = (bytes - 1) / 16;
  763.                         c = (bytes - 1) % 16;
  764.                     }
  765.  
  766.                     wmove (alphawin, r, c);
  767.                     wrefresh (alphawin);
  768.                 }
  769.  
  770.                 break;
  771.  
  772.             case 'H': /* hex modify */
  773.                 dbg_msg ("edit hex");
  774.                 stay = 1;
  775.                 r = c = hexc = 0;
  776.                 if (bytes == 0) break;
  777.                 touchwin (stdscr);
  778.                 refresh ();
  779.                 wmove (hexwin, r, hexc);
  780.                 wrefresh (hexwin);
  781.  
  782.                 while ((z = wgetch (hexwin)) != DEL)
  783.                 {
  784.                     if (!arrow (z, &r, &c))
  785.                     {
  786.                         hexc = c * 3;
  787.                         z = toupper (z);
  788.                         if (!isxdigit (z))
  789.                         {
  790.                             beep ();
  791.                         }
  792.                         else
  793.                         {
  794.                             waddch (hexwin, tolower (z));
  795.                             wrefresh (hexwin);
  796.  
  797.                             if (z > '9') z -= 7;
  798.  
  799.                             h = (z & m) << 4;
  800.  
  801.                             while (2)
  802.                             {
  803.                                 z = EOF;
  804.                                 z = getch ();
  805.                                 if (z == EOF)
  806.                                 {
  807.                                     pbrk = 0;
  808.                                     h = -1;
  809.                                     break;
  810.                                 }
  811.                                 z = toupper (z);
  812.                                 if (!isxdigit (z))
  813.                                 {
  814.                                     beep ();
  815.                                 }
  816.                                 else
  817.                                 {
  818.                                     waddch (hexwin, tolower (z));
  819.                                     wrefresh (hexwin);
  820.                                     if (z > '9') z -= 7;
  821.  
  822.                                     h |= z & m;
  823.                                     break;
  824.                                 }
  825.                             }
  826.  
  827.                             if (h < 0)
  828.                             {
  829.                                 wmove (hexwin, r, hexc);
  830.                                 if (record[r][c] < '\0')
  831.                                 {
  832.                                     wprintw (hexwin, "%x%x",
  833.                                         (record[r][c] >> 4) & m,
  834.                                         record[r][c] & m);
  835.                                 }
  836.                                 else
  837.                                 {
  838.                                     wprintw (hexwin, "%02x", record[r][c]);
  839.                                 }
  840.                                 wrefresh (hexwin);
  841.                                 break;
  842.                             }
  843.  
  844.                             record[r][c] = z = h;
  845.                             mod = 1;
  846.  
  847.                             if (ebcdic) icc (&z, 1,"EA");
  848.  
  849.                             wmove (alphawin, r, c);
  850.                             if (isascii (z) && isprint (z))
  851.                                 waddch (alphawin, z);
  852.                             else waddch (alphawin, '.');
  853.                             wrefresh (alphawin);
  854.  
  855.                             if (c == 15)
  856.                             {
  857.                                 if (r == 15) beep ();
  858.                                 else
  859.                                 {
  860.                                     c = 0;
  861.                                     ++r;
  862.                                 }
  863.                             }
  864.                             else
  865.                             {
  866.                                 c++;
  867.                             }
  868.                         }
  869.                     }
  870.  
  871.                     if (r * 16 + c >= bytes)
  872.                     {
  873.                         beep ();
  874.                         r = (bytes - 1) / 16;
  875.                         c = (bytes - 1) % 16;
  876.                     }
  877.  
  878.                     hexc = c * 3;
  879.                     wmove (hexwin, r, hexc);
  880.                     wrefresh (hexwin);
  881.                 }
  882.                 break;
  883.  
  884.             case 'W': /* write record */
  885.                 stay = 1;
  886.                 status = lseek (fid, position, 0);
  887.                 if (status != position)
  888.                 {
  889.                     move (22, 0);
  890.                     clrtoeol ();
  891.                     perror (filename);
  892.                     errmsg ("error positioning in file");
  893.                     beep ();
  894.                 }
  895.                 if (swab) schwapp (record, 256);
  896.                 if (write (fid, record, bytes) != bytes)
  897.                 {
  898.                     errmsg ("error writing to file");
  899.                     sleep (1);
  900.                     reset (0);
  901.                     exit (0);
  902.                 }
  903.                 if (swab) schwapp (record, 256);
  904.                 mod = 0;
  905.                 errmsg ("Record written");
  906.                 break;
  907.  
  908.             case    '\n':        /* newline - next page            */
  909.             case    '\r':
  910.                 if (mod)
  911.                 {
  912.                     errmsg ("No write since last change");
  913.                     stay = 1;
  914.                 }
  915.                 else
  916.                 {
  917.                     ++recno;
  918.                     if (!rawfile && (recno * 256) >= size)
  919.                     {
  920.                         recno--;
  921.                         beep ();
  922.                         errmsg ("No more records in file");
  923.                         stay = 1;
  924.                     }
  925.                     else stay = 0;
  926.                 }
  927.                 break;
  928.  
  929.             default:
  930.                 if (isascii (zp) && isprint (zp))
  931.                     errmsg ("Unknown command: %d", zp);
  932.                 else
  933.                     errmsg ("Unknown command: %d", zp + '@');
  934.                 beep ();
  935.                 stay = 1;
  936.                 break;
  937.         } /* end switch zp */
  938.         refresh ();
  939.     }
  940.  
  941.     if (windowed)
  942.     {
  943.         reset (0);
  944.     }
  945.     status = close (fid);
  946.  
  947.     exit (status);
  948. }
  949. /*S show - display a record on the terminal */
  950. /*H show */
  951. /*E*/
  952. show (bytes, record, filename, size, recno, position,
  953.       m,reclen, dump, ebcdic, swab, block, honly)
  954. int bytes;
  955. int size;
  956. int recno;
  957. int position;
  958. int m;
  959. int reclen;
  960. int dump;
  961. int ebcdic;
  962. int swab;
  963. int honly;
  964. char record[16][16];
  965. char *filename;
  966. {
  967.     int        i;
  968.     int        j;
  969.     char    s;
  970.     char    temp[16];
  971.     char    *look = NULL;
  972.  
  973.     int        row = 0;
  974.     int        col = 0;
  975.  
  976.     if (dump) printf ("\n\n");
  977.  
  978.     if (debug)
  979.     {
  980.         getyx (stdscr, row, col);
  981.         move (23,0);
  982.         printw ("show: %d|%d|%s|%d|%d|%d|%#x|%d|%d|%d|%d|%d|%d",
  983.             bytes, record, filename, size, recno, position,
  984.             m, reclen, dump, ebcdic, swab, block, honly);
  985.         move (row, col);
  986.         row = col = 0;
  987.     }
  988.  
  989.     if (!dump) move (0, 0);
  990.     outstr ("FILE: %s ", filename);
  991.     if (block_spec) outstr ("(block special)");
  992.     else if (char_spec) outstr ("(character special)");
  993.     else if (fifo_spec) outstr ("(fifo (named pipe))");
  994.     else if (dir_spec) outstr ("(directory - %ld)", size);
  995.     else outstr ("(%ld)", size);
  996.  
  997.     if (ebcdic) outstr (" - EBCDIC");
  998.     else outstr (" - ASCII");
  999.     if (swab) outstr (" - SWAP");
  1000.     if (block) outstr (" - BLOCK (%d)", block);
  1001.     if (reclen) outstr (" - RECORD (%d)", reclen);
  1002.  
  1003.     if (!dump)
  1004.     {
  1005.         clrtoeol ();
  1006.         move (1,0);
  1007.         printw ("PAGE: %d (%d)", recno, position);
  1008.         clrtoeol ();
  1009.         row = 2;
  1010.     }
  1011.     else
  1012.     {
  1013.         printf ("\nPAGE: %d (%d)\n", recno, position);
  1014.     }
  1015.  
  1016.     if (honly)
  1017.     {
  1018.         look = (char *) record;
  1019.         for (j=0;j<256;++j)
  1020.         {
  1021.             if (*look++ != '\0')
  1022.             {
  1023.                 look = NULL;
  1024.                 break;
  1025.             }
  1026.         }
  1027.     }
  1028.  
  1029.     if (!dump) move (row, col);
  1030.  
  1031.     outstr ("    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf");
  1032.     outstr ("      0123456789abcdef");
  1033.  
  1034.     if (!dump)
  1035.     {
  1036.         row += 2;
  1037.         move (row, col);
  1038.     }
  1039.     else
  1040.     {
  1041.         printf ("\n\n");
  1042.     }
  1043.     for (i=0; i<=bytes/16; ++i)
  1044.     {
  1045.         if (honly && look != NULL)
  1046.         {
  1047.             i = 16;
  1048.             continue;
  1049.         }
  1050.         if (i*16+1 > bytes) continue;
  1051.  
  1052.         outstr ("%02x: ", i);
  1053.  
  1054.         for (j=0; j<16; ++j)
  1055.         {
  1056.             if (i*16+j < bytes)
  1057.             {
  1058.                 if (record[i][j] < '\0')
  1059.                     outstr ("%x%x ",
  1060.                         (record[i][j] >> 4) & m, record[i][j] & m);
  1061.                 else
  1062.                     outstr ("%02x ", record[i][j]);
  1063.  
  1064.                 s = ' ';
  1065.                 if (reclen > 0 && (position+i*16+j+1)%reclen == 0)
  1066.                     s = ':';
  1067.                 if (block > 0 && (position+i*16+j+1)%block == 0)
  1068.                 {
  1069.                     if (s == ' ')
  1070.                         s = '/';
  1071.                     else
  1072.                         s = '%';
  1073.                 }
  1074.                 if (s != ' ')
  1075.                     outstr ("\b%c", s);
  1076.             }
  1077.             else
  1078.             {
  1079.                 outstr ("   ");
  1080.             }
  1081.         }
  1082.  
  1083.         outstr ("     ");
  1084.  
  1085.         copyrec (record[i], temp, 16);
  1086.  
  1087.         if (ebcdic) icc (temp, 16, "EA");
  1088.  
  1089.         for (j = 0; j < 16 && i*16+j < bytes; ++j)
  1090.         {
  1091.             if (temp[j] < ' ') outch ('.');
  1092.             else outstr ("%c", temp[j]);
  1093.         }
  1094.  
  1095.         if (!dump)
  1096.         {
  1097.             move (++row, col);
  1098.         }
  1099.         else
  1100.         {
  1101.             printf ("\n");
  1102.         }
  1103.     }
  1104.  
  1105.     if (!dump)
  1106.     {
  1107.         clrtobot ();
  1108.         refresh ();
  1109.     }
  1110.  
  1111.     return;
  1112. }
  1113. /*S breakp - set pbrk on interrupt */
  1114. /*H breakp */
  1115. /*E*/
  1116. void breakp (i)
  1117. int i;
  1118. {
  1119.     int s;
  1120.     extern int pbrk;
  1121.     s = (int) signal (SIGINT, breakp);
  1122.     pbrk = i;
  1123. }
  1124. /*S bread - buffered read */
  1125. /*H bread */
  1126. /*E*/
  1127. int bread (fid, record, want, block)
  1128. int fid, want, block;
  1129. char *record;
  1130. {
  1131.     int i, j, k;
  1132.     int what, bytes, orig;
  1133.     static char buffer[10240];
  1134.     static int left, arrow;
  1135.     static int flag = 1;
  1136.  
  1137.     if (flag)
  1138.     {
  1139.         left = 0;
  1140.         arrow = 0;
  1141.         flag = 0;
  1142.     }
  1143.  
  1144.     if (block == 0)
  1145.         return (read (fid, record, want));
  1146.  
  1147.     if (block & 1) ++block;
  1148.  
  1149.     orig = what = want;
  1150.     while (1)
  1151.     {
  1152.         if (left < want)
  1153.         {
  1154.             if (left)
  1155.             {
  1156.                 copyrec (&buffer[arrow], record, left);
  1157.                 record += left;
  1158.                 want -= left;
  1159.             }
  1160.  
  1161.             arrow = 0;
  1162.             left = 0;
  1163.  
  1164.             if ((bytes = read (fid, buffer, block)) < 0)
  1165.             {
  1166.                 what = bytes;
  1167.                 break;
  1168.             }
  1169.  
  1170.             if (bytes == 0)
  1171.             {
  1172.                 what = orig - want;
  1173.                 break;
  1174.             }
  1175.  
  1176.             left = bytes;
  1177.         }
  1178.         else
  1179.         {
  1180.             copyrec (&buffer[arrow], record, want);
  1181.             arrow += want;
  1182.             left -= want;
  1183.             break;
  1184.         }
  1185.     }
  1186.  
  1187.     return (what);
  1188. }
  1189. /*S schwapp - swap bytes in place */
  1190. /*H schwapp */
  1191. /*E*/
  1192. void
  1193. schwapp (ptr, nch)
  1194. register char *ptr;
  1195. register int nch;
  1196. {
  1197.     register int i;
  1198.     register char c;
  1199.     register char *ptra = ptr + 1;
  1200.  
  1201.     if (nch & 1) --nch;
  1202.  
  1203.     for (i = 0; i < nch; i += 2, ptr += 2, ptra += 2)
  1204.     {
  1205.         c = *ptr;
  1206.         *ptr = *ptra;
  1207.         *ptra = c;
  1208.     }
  1209.     return;
  1210. }
  1211. /*S copyrec - transfer bytes from f to t for nbytes bytes */
  1212. /*H copyrec */
  1213. /*E*/
  1214. void
  1215. copyrec (f, t, nbytes)
  1216. register char *f;
  1217. register char *t;
  1218. register int nbytes;
  1219. {
  1220.     register int i;
  1221.  
  1222.     for (i = 0; i < nbytes; i++, f++, t++) *t = *f;
  1223.  
  1224.     return;
  1225. }
  1226. /*S ebcdic codes corresponding to ascii - translation table */
  1227. /*Page Eject*/
  1228. char ebcdic_codes[] = {
  1229. 0, 0x1, 0x2, 0x3, 0x37, 0x2d, 0x2e, 0x2f, 0x16,
  1230. 0x5, 0x25, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11,
  1231. 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f,
  1232. 0x27, 0x1c, 0x1d, 0x1e, 0x1f, 0x40, 0x5a, 0x7f, 0x7b,
  1233. 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b,
  1234. 0x60, 0x4b, 0x61, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
  1235. 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e,
  1236. 0x6f, 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  1237. 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  1238. 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
  1239. 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, 0x79, 0x81, 0x82,
  1240. 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92,
  1241. 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0xa2, 0xa3,
  1242. 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0,
  1243. 0x5f, 0x7 };
  1244. /*S icc - internal code conversion */
  1245. /*H icc */
  1246. /*E*/
  1247. void
  1248. icc (buf, nch, type)
  1249. register char *buf;
  1250. register int nch;
  1251. char *type;
  1252. {
  1253.     register int i;
  1254.     register int j;
  1255.  
  1256.     if (!strcmp (type, "AE"))
  1257.     {
  1258.         for (i = 0; i < nch; i++, buf++)
  1259.         {
  1260.             *buf = ebcdic_codes[*buf];
  1261.         }
  1262.     }
  1263.     else if (!strcmp (type, "EA"))
  1264.     {
  1265.         for (i = 0; i < nch; i++, buf++)
  1266.         {
  1267.             for (j = 0; j < 128; j++)
  1268.             {
  1269.                 if (*buf == ebcdic_codes[j])
  1270.                 {
  1271.                     *buf = j;
  1272.                     break;
  1273.                 }
  1274.             }
  1275.         }
  1276.     }
  1277.  
  1278.     return;
  1279. }
  1280. /*S ckfile - check on existence, accessibility, and type of file */
  1281. /*H ckfile */
  1282. /*E*/
  1283. ckfile (filename, sizep)
  1284. char    *filename;
  1285. long    *sizep;
  1286. {
  1287.     register int fid = 0;
  1288.  
  1289.     if (access (filename, 0) < 0)
  1290.     {
  1291.         errmsg ("file not found (%s)", filename);
  1292.         fid = -1;
  1293.     }
  1294.  
  1295.     if (block || pause || dump)
  1296.     {
  1297.         fid = open (filename, O_RDONLY, 0);
  1298.     }
  1299.     else
  1300.     {
  1301.         fid = open (filename, O_RDWR, 0);
  1302.     }
  1303.  
  1304.     if (fid < 0)
  1305.     {
  1306.         errmsg ("error opening file %s", filename);
  1307.         perror (filename);
  1308.         fid = -1;
  1309.     }
  1310.     else
  1311.     {
  1312.         errmsg ("File %s opened successfully ", filename);
  1313.         if (fstat (fid, &sb) == -1)
  1314.         {
  1315.             fprintf (stderr, "Can't stat\n");
  1316.             perror (filename);
  1317.             fid = -1;
  1318.         }
  1319.         else
  1320.         {
  1321.             block_spec = (sb.st_mode & S_IFMT) == S_IFBLK;
  1322.             char_spec = (sb.st_mode & S_IFMT) == S_IFCHR;
  1323.             fifo_spec = (sb.st_mode & S_IFMT) == S_IFIFO;
  1324.             dir_spec = (sb.st_mode & S_IFMT) == S_IFDIR;
  1325.             rawfile = block_spec || char_spec || fifo_spec;
  1326.  
  1327.             if (rawfile) *sizep = -1;
  1328.             else
  1329.             {
  1330.                 if (sb.st_size == 0)
  1331.                 {
  1332.                     fprintf (stderr,
  1333.                         "file %s is empty (zero bytes)\n",
  1334.                         filename);
  1335.                     fid = -1;
  1336.                 }
  1337.                 *sizep = sb.st_size;
  1338.             }
  1339.         }
  1340.     }
  1341.  
  1342.     return fid;
  1343. }
  1344. /*S dohelp - display help text */
  1345. /*H dohelp */
  1346. /*E*/
  1347. dohelp ()
  1348. {
  1349.     static char *helptxt[] = {
  1350.     "!   - execute command in the shell",    "a   - edit ascii portion",
  1351.     "-x   - toggle command line option",    "f   - display first page of file",
  1352.     "<cr> - display next page",    NULL,
  1353.     "?    - display this help text",    "h   - edit hexadecimal portion",
  1354.     "DEL  - quit the program",        "l   - display last page of file",
  1355.     "\\    - display previous page",        "nnn - direct addressing",
  1356.     "/    - search for ASCII string",        "q   - quit the program",
  1357.     "^f   - select named file",        "r   - reread the current page",
  1358.     "^n   - select next file",        "u   - undo all changes to page",
  1359.     "^p   - select previous file",        "w   - write out changed page",
  1360.     "^q   - quit without writing changes",    NULL,
  1361.     "^r   - redraw the screen",    NULL,
  1362.     "^x   - turn on debug",    NULL,
  1363.     "----------------------------------------------------------------", NULL,
  1364.     "direct addressing: nnnS, where nnn = some number, and", NULL,
  1365.     "                      S = type suffix", "b = block (512)",
  1366.     NULL, "k = kilobyte (1024)",
  1367.     NULL, "l = long word (4)",
  1368.     NULL, "p = page (256)",
  1369.     NULL, "w = word (2)",
  1370.     NULL, "<cr> = byte",
  1371.     };
  1372.  
  1373.     static int nmsg = sizeof helptxt / sizeof (char *);
  1374.     register int row = 0;
  1375.     register int i;
  1376.  
  1377.     register WINDOW *helpwin;
  1378.     extern WINDOW *newwin ();
  1379.  
  1380.     helpwin = newwin (LINES, COLS, 0, 0);
  1381.     werase (helpwin);
  1382.     wrefresh (helpwin);
  1383.  
  1384.     wmove (helpwin, 0, 1);
  1385.     waddstr (helpwin,
  1386. "---------------------------------- HELP ----------------------------------");
  1387.  
  1388.     for (row = 1, i = 0; i < nmsg; i+=2)
  1389.     {
  1390.         if (helptxt[i])
  1391.         {
  1392.             wmove (helpwin, row, 1);
  1393.             waddstr (helpwin, helptxt[i]);
  1394.         }
  1395.         if (i+1 <= nmsg && helptxt[i+1])
  1396.         {
  1397.             wmove (helpwin, row, 41);
  1398.             waddstr (helpwin, helptxt[i+1]);
  1399.         }
  1400.         row++;
  1401.     }
  1402.  
  1403.     wmove (helpwin, 23, 0);
  1404.     wstandout (helpwin);
  1405.     waddstr (helpwin, " <Press any key> ");
  1406.     wstandend (helpwin);
  1407.     wclrtoeol (helpwin);
  1408.     wrefresh (helpwin);
  1409.     wgetch (helpwin);
  1410.     werase (helpwin);
  1411.     wrefresh (helpwin);
  1412.     delwin (helpwin);
  1413.  
  1414.     return;
  1415. }
  1416. /*S reset - reset terminal to original state */
  1417. /*H reset */
  1418. /*E*/
  1419. void reset (sig)
  1420. int sig;
  1421. {
  1422.     move (23, 0);
  1423.     refresh ();
  1424.     endwin ();
  1425.     if (sig) fprintf (stderr, "killed with signal %d\n", sig);
  1426.     exit (sig);
  1427. }
  1428. /*S arrow - determine if current character is a cursor control key */
  1429. /*H arrow */
  1430. /*E*/
  1431. arrow (k, r, c, type)
  1432. register int k;
  1433. register int *r;
  1434. register int *c;
  1435. register int type;
  1436. {
  1437.     register ret = 1;
  1438.  
  1439.     if (k == KEY_UP)
  1440.     {
  1441.         if (*r == 0) beep ();
  1442.         else (*r)--;
  1443.     }
  1444.     else if (k == KEY_DOWN || k == '\n')
  1445.     {
  1446.         if (*r == 15) beep ();
  1447.         else (*r)++;
  1448.     }
  1449.     else if (k == KEY_LEFT || k == '\b' )
  1450.     {
  1451.         if (*c == 0)
  1452.         {
  1453.             if (*r == 0) beep ();
  1454.             else
  1455.             {
  1456.                 *c = 15;
  1457.                 (*r)--;
  1458.             }
  1459.         }
  1460.         else (*c)--;
  1461.     }
  1462.     else if (k == KEY_RIGHT)
  1463.     {
  1464.         if (*c == 15)
  1465.         {
  1466.             if (*r == 15) beep ();
  1467.             else
  1468.             {
  1469.                 *c = 0;
  1470.                 (*r)++;
  1471.             }
  1472.         }
  1473.         else (*c)++;
  1474.     }
  1475.     else if (k == KEY_HOME)
  1476.     {
  1477.         *r = *c = 0;
  1478.     }
  1479.     else
  1480.     {
  1481.         ret = 0;
  1482.     }
  1483.  
  1484.     return ret;
  1485. }
  1486. /*S dbg_msg - print a debug message */
  1487. /*H dbg_msg */
  1488. /*E*/
  1489. dbg_msg (msg)
  1490. register char *msg;
  1491. {
  1492.     if (debug && !dump)
  1493.     {
  1494.         errmsg (msg);
  1495.     }
  1496.  
  1497.     return;
  1498. }
  1499. /*S getstring - get a character string from the terminal */
  1500. /*H getstring */
  1501. /*E*/
  1502. char *
  1503. getstring ()
  1504. {
  1505.     static char buf[512];
  1506.  
  1507.     register int c;
  1508.     register char *p = buf;
  1509.     register int col = 0;
  1510.  
  1511.     move (22, 0);
  1512.     clrtoeol ();
  1513.     refresh ();
  1514.  
  1515.     while ((c = getch ()) != '\r')
  1516.     {
  1517.         if (isascii (c) && isprint (c))
  1518.         {
  1519.             move (22, col);
  1520.             addch (c);
  1521.             *p++ = c;
  1522.             col++;
  1523.         }
  1524.         else if (c == '\b')
  1525.         {
  1526.             p--;
  1527.             col--;
  1528.             move (22, col);
  1529.             addch (' ');
  1530.             move (22, col);
  1531.         }
  1532.         refresh ();
  1533.     }
  1534.  
  1535.     refresh ();
  1536.  
  1537.     *p = '\0';
  1538.  
  1539.     return buf;
  1540. }
  1541. /*S getnum - retrieve a number from the terminal */
  1542. /*H getnum */
  1543. /*E*/
  1544. long
  1545. getnum (frst_char, hex)
  1546. register int frst_char;
  1547. register int hex;
  1548. {
  1549.     static char buf[64];
  1550.  
  1551.     register int c;
  1552.     register char *p = buf;
  1553.     register int col = 0;
  1554.  
  1555.     register long retval = 0;
  1556.  
  1557.     move (22, 0);
  1558.     clrtoeol ();
  1559.     if (frst_char)
  1560.     {
  1561.         addch (frst_char);
  1562.         *p++ = frst_char;
  1563.         col++;
  1564.         refresh ();
  1565.     }
  1566.  
  1567.     while ((c = getch()) != '\r')
  1568.     {
  1569.         if (isascii (c))
  1570.         {
  1571.             if ((hex && isxdigit (c)) || isdigit (c))
  1572.             {
  1573.                 move (22, col);
  1574.                 addch (c);
  1575.                 *p++ = c;
  1576.                 col++;
  1577.             }
  1578.             else if (c == '\b')
  1579.             {
  1580.                 p--;
  1581.                 col--;
  1582.                 move (22, col);
  1583.                 addch (' ');
  1584.                 move (22, col);
  1585.             }
  1586.             else
  1587.             {
  1588.                 break;            /* some character typing the value    */
  1589.             }
  1590.             refresh ();
  1591.         }
  1592.     }
  1593.  
  1594.     *p = '\0';
  1595.  
  1596.     retval = atol (buf);
  1597.  
  1598.     mvprintw (22, 0, "%ld", retval);
  1599.     switch (c)
  1600.     {
  1601.         case    'b':            /* block - 512 bytes                */
  1602.             retval *= 512;
  1603.             break;
  1604.         case    'k':            /* 1024 bytes                        */
  1605.             retval *= 1024;
  1606.             break;
  1607.         case    'l':            /* long word - 4 bytes                */
  1608.             retval *= 4;
  1609.             break;
  1610.         case    'p':            /* page - 256 bytes                    */
  1611.             retval *= 256;
  1612.             break;
  1613.         case    'w':            /* word - 2 bytes                    */
  1614.             retval *= 2;
  1615.             break;
  1616.         case    '\r':            /* just clear it for display        */
  1617.             c = '\0';
  1618.             break;
  1619.     }
  1620.  
  1621.     printw ("%c -> %ld byte offset", c, retval);
  1622.     clrtoeol ();
  1623.  
  1624.     refresh ();
  1625.  
  1626.     return retval;
  1627. }
  1628. /*S search - look for an ascii string in the file */
  1629. /*H search */
  1630. /*E*/
  1631. search (fid)
  1632. register int fid;
  1633. {
  1634.     long    curpos = position;
  1635.     long    currec = recno;
  1636.  
  1637.     char    lrecord[sizeof record + 1];
  1638.  
  1639.     register int i;
  1640.     register int matched = 0;
  1641.     register int srch_len;
  1642.  
  1643.     register char *cp = getstring ();
  1644.     register char *rp;
  1645.  
  1646.     int row, col;
  1647.  
  1648.     srch_len = strlen (cp);
  1649.     copyrec (record, lrecord, sizeof record);
  1650.     lrecord[256] = '\0';
  1651.  
  1652.     pbrk = 0;
  1653.  
  1654.     wmove (errwin, 0, 0);
  1655.     wstandout (errwin);
  1656.     wmove (errwin, 0, 40);
  1657.     wstandend (errwin);
  1658.     wmove (errwin, 0, 1);
  1659.     waddstr (errwin, "..searching record ");
  1660.     getyx (errwin, row, col);
  1661.  
  1662.     do
  1663.     {
  1664.         mvwprintw (errwin, row, col, "%ld", currec);
  1665.         wrefresh (errwin);
  1666.  
  1667.         for (i = 0, rp = lrecord, matched = 0;
  1668.              !matched && i < 256;
  1669.              rp++, i++)
  1670.         {
  1671.             if (*cp == *rp && !strncmp (cp, rp, srch_len))
  1672.             {
  1673.                 matched = 1;
  1674.                 break;
  1675.             }
  1676.         }
  1677.  
  1678.         if (!matched)
  1679.         {
  1680.             bytes = bread (fid, lrecord, 256, block);
  1681.             currec++;
  1682.             lrecord[256] = '\0';
  1683.         }
  1684.     }    while (!pbrk && bytes && !matched);
  1685.  
  1686.     if (matched)
  1687.     {
  1688.         recno = currec;
  1689.         stay = 0;
  1690.         copyrec (record, unch_rec, sizeof record);
  1691.         werase (errwin);
  1692.         wrefresh (errwin);
  1693.     }
  1694.     else
  1695.     {
  1696.         errmsg ("String %s not found", cp);
  1697.         stay = 1;
  1698.     }
  1699.  
  1700.     return;
  1701. }
  1702. errmsg (fmt, arg1, arg2, arg3, arg4)
  1703. register char *fmt;
  1704. register char *arg1;
  1705. register char *arg2;
  1706. register char *arg3;
  1707. register char *arg4;
  1708. {
  1709.     int y, x;
  1710.  
  1711.     if (!dump)
  1712.     {
  1713.         getyx (stdscr, y, x);
  1714.         wmove (errwin, 0, 0);
  1715.         wstandout (errwin);
  1716.         wprintw (errwin, fmt, arg1, arg2, arg3, arg4);
  1717.         wstandend (errwin);
  1718.         wclrtoeol (errwin);
  1719.         wrefresh (errwin);
  1720.         move (y, x);
  1721.     }
  1722.     else
  1723.     {
  1724.         fprintf (stderr, fmt, arg1, arg2, arg3, arg4);
  1725.     }
  1726.     return;
  1727. }
  1728. outstr (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
  1729. register char *fmt;
  1730. register char *arg1;
  1731. register char *arg2;
  1732. register char *arg3;
  1733. register char *arg4;
  1734. register char *arg5;
  1735. register char *arg6;
  1736. register char *arg7;
  1737. {
  1738.     if (dump) printf (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  1739.     else printw (fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  1740.  
  1741.     return;
  1742. }
  1743. outch (ch)
  1744. register char ch;
  1745. {
  1746.     if (dump) putchar (ch);
  1747.     else addch (ch);
  1748.  
  1749.     return;
  1750. }
  1751.